
#region Imported Namespaces
using System;
using System.Data;
using System.Data.SqlClient;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
#endregion

namespace PHSRAG.Insight21.BusinessObjects
{
	#region Interface IBusinessObject
	/// <summary>
	/// The IBusinessObject interface defines the public contract between business objects and their clients.
	/// </summary>
	public interface IBusinessObject
	{
		/// <summary>
		/// Cache this instance of the object (using the cache policy).
		/// </summary>
		void Cache();

		/// <summary>
		/// Remove this instance of the object from the cache (using the cache policy).
		/// </summary>
		void UnCache();
	}
	#endregion

	#region class BusinessObject
	/// <summary>
	/// The BusinessObject class is the base for all other business objects. The only member it defines is
	/// of type DataSet, and is the data container for the object. Derived classes are expected to set the
	/// DataSet as part of their own initialization.
	/// 
	/// Note that in this model, business object seldom store their state in member variables. Instead, they
	/// simply rely on the DataSet to act truly as their data container, and the classes simply provide
	/// accessors (get/set) wired to the DataSet. In such a context, business objects simply behave as
	/// facades to the data container.
	/// The assumption is that the data for the entire object hierarchy for each business object is entirely
	/// within a single DataSet which may contain as many DataTable instances as there are levels in the
	/// class hierarchy. The names of such DataTables are expected to be sensible enough to make the
	/// association between a DataTable and the corresponding facade natural.
	/// 
	/// IMPORTANT: One of the most basic requirement is that each DataTable has an identity/autonumber column.
	/// Violating this requirement will render the update logic to either misbehave or not work at all.
	/// 
	/// This class defines the Load method which is to be implemented by derived classes. This is the way
	/// by which the DataSet associated with the derived object is loaded from some data repository.
	/// 
	/// A dervived class loads its state by getting a DataSet that represents its state. It calls upon the
	/// DataContainer property of the BusinessObject class to initialize the reference to the DataSet.
	/// Access to the object's state is via accessors wired to the appropriate field in the appropriate
	/// DataTable within the DataSet.
	/// </summary>
	public abstract class BusinessObject : IBusinessObject
	{
		#region Instance Variables
		private ICachePolicy	cachePolicy;
		private DataSet			dataContainer;
		#endregion

		#region Instance Properties (protected)
		/// <summary>Get/Set the cache policy</summary>
		protected ICachePolicy CachePolicy	{ get { return cachePolicy; }	set { cachePolicy = value; } }

		/// <summary>Get/Set the data set which would typically contains all data</summary>
		protected DataSet DataContainer	{ get { return dataContainer; }	set { dataContainer = value; } }
		#endregion

		#region Constructor
		/// <summary>
		/// Initialize the cache policy with the specified reference.
		/// </summary>
		/// <param name="cachePolicy">Reference to the cache policy interface</param>
		protected BusinessObject(ICachePolicy cachePolicy)
		{
			CachePolicy = cachePolicy;
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Get the data set which contains data associated with this object (its concrete implementation). The reason why
		/// this is NOT a property is simply that there already exists a protected property named DataContainer.
		/// </summary>
		/// <returns>Reference to the DataSet which holds the data</returns>
		public DataSet GetDataContainer()
		{
			return DataContainer;
		}
		#endregion

		#region IBusinessObject Members
		/// <summary>
		/// Cache this instance of the object (using the cache policy).
		/// </summary>
      public virtual void Cache()
      {
         throw new Exception(string.Format("Cache() method not implemented by {0}.", GetType() ));
      }

		/// <summary>
		/// Remove this instance of the object from the cache (using the cache policy).
		/// </summary>
		public virtual void UnCache()
      {
         throw new Exception(string.Format("UnCache() method not implemented by {0}.", GetType() ));
      }
      #endregion

		#region Abstract Methods
		/// <summary>
		/// Load the data set with data.
		/// </summary>
		/// <param name="connectionString">Connection string to the database</param>
		/// <param name="args">Any arguments to be passed to the underlying data access layer</param>
		public abstract void Load(string connectionString, params object[] args);
		#endregion

		#region Public Methods
		/// <summary>
		/// Dispose of the data container if one was loaded.
		/// </summary>
		public virtual void Purge()
		{
			if (dataContainer != null)
				dataContainer.Dispose();
		}
		#endregion
	}
	#endregion

	#region class SaveableBusinessObject
	/// <summary>
	/// The SaveableBusinessObject class simply adds the facility to save the state of a business object.
	/// 
	/// This class declares the Save method which must be implemented by derived classes. This is the way
	/// by which the DataSet associated with the derived object is saved back to its repository.
	/// </summary>
	public abstract class SaveableBusinessObject : BusinessObject
	{
		#region Constructor
		/// <summary>
		/// Initialize the base object with the specified cache policy.
		/// </summary>
		/// <param name="cachePolicy">Reference to the cache policy interface</param>
		protected SaveableBusinessObject(ICachePolicy cachePolicy) : base(cachePolicy)
		{
		}
		#endregion

		#region Abstract Methods
		/// <summary>
		/// Save this instance of the object to the database.
		/// </summary>
		/// <param name="connectionString">Connection string to the database</param>
		/// <param name="args">Any arguments to be passed to the underlying data access layer</param>
		public abstract	void Save(string connectionString, params object[] args);
		#endregion
	}
	#endregion

	#region class TransactionalBusinessObject
	/// <summary>
	/// The TransactionalBusinessObject class simply adds the facility to save the state of a business object
	/// using the transaction created by the caller.
	/// 
	/// This class declares the Save method which must be implemented by derived classes. This is the way
	/// by which the DataSet associated with the derived object is saved back to its repository.
	/// </summary>
	public abstract class TransactionalBusinessObject : BusinessObject
	{
		#region Constructor
		/// <summary>
		/// Initialize the base object with the specified cache policy.
		/// </summary>
		/// <param name="cachePolicy">Reference to the cache policy interface</param>
		protected TransactionalBusinessObject(ICachePolicy cachePolicy)	: base(cachePolicy)
		{
		}
		#endregion

		#region Abstract Methods
		/// <summary>
		/// Save this instance of the object to the database using the specified transaction.
		/// </summary>
		/// <param name="transaction">A transaction on an open connection</param>
		/// <param name="args">Any arguments to be passed to the underlying data access layer</param>
		public abstract	void Save(SqlTransaction transaction, params object[] args);
		#endregion
	}
	#endregion
}

// --- EOF ---
